using System.Globalization;
using System.IO;
using Microsoft.Practices.RecipeFramework;
using Microsoft.VisualStudio.Shell;
using VSSDKAssist.Assets.Actions.Base;
using VSSDKAssist.Assets.Actions.General;
using VSSDKAssist.Assets.Actions.VisualStudio;
using VSSDKAssist.Enums;
using VSSDKAssist.Recipes.Common.Helpers;

namespace VSSDKAssist.Recipes.CreateVSPackageDeploymentInfo
{
	/// <summary>
	/// Action that creates a VS Package deployment information file
	/// </summary>
	public class CreateVSPackageDeploymentInfoAction : ActionBase
	{
		#region Properties
		private EnvDTE.Project project;

		/// <summary>
		/// Gets or sets the project.
		/// </summary>
		/// <value>The project.</value>
		[Input(Required = true)]
		public EnvDTE.Project Project
		{
			get
			{
				return this.project;
			}
			set
			{
				this.project = value;
			}
		}

		private EnvDTE.CodeClass codeClass;

		/// <summary>
		/// Gets or sets the code class.
		/// </summary>
		/// <value>The code class.</value>
		[Input(Required = true)]
		public EnvDTE.CodeClass CodeClass
		{
			get
			{
				return this.codeClass;
			}
			set
			{
				this.codeClass = value;
			}
		}

		private DeploymentInfo deploymentInfo;

		/// <summary>
		/// Gets or sets the deployment info.
		/// </summary>
		/// <value>The deployment info.</value>
		[Input(Required = true)]
		public DeploymentInfo DeploymentInfo
		{
			get { return deploymentInfo; }
			set { deploymentInfo = value; }
		}

		private RegistrationMethod registrationMethod;

		/// <summary>
		/// Gets or sets the registration method.
		/// </summary>
		/// <value>The registration method.</value>
		[Input(Required = true)]
		public RegistrationMethod RegistrationMethod
		{
			get { return registrationMethod; }
			set { registrationMethod = value; }
		}
		#endregion

		#region Protected Implementation
		/// <summary>
		/// Called when [execute].
		/// </summary>
		protected override void OnExecute()
		{
			string outputPath = this.Project.ConfigurationManager.ActiveConfiguration.Properties.Item("OutputPath").Value.ToString();
			string buildPath = this.Project.Properties.Item("LocalPath").Value.ToString();
			string targetName = this.Project.Properties.Item("OutputFileName").Value.ToString();
			string assemblyFile = Path.Combine(buildPath, Path.Combine(outputPath, targetName));
			string projectPath = Path.GetDirectoryName(this.Project.Properties.Item("FullPath").Value.ToString());
			string deploymentFile = this.CodeClass.Name;

			if(File.Exists(assemblyFile))
			{
				using(ExecuteProcessAction executeProcessAction = new ExecuteProcessAction())
				{
					executeProcessAction.Site = this.Site;
					executeProcessAction.FileName =
							Path.Combine(
								Path.Combine(
									CommonHelper.GetVSSdkInstallPath(),
									Constants.VSSdkToolRelPath),
									Constants.RegPkgTool);

					executeProcessAction.Arguments = GetArguments(assemblyFile, projectPath, ref deploymentFile);

					if(File.Exists(deploymentFile) &&
						VSSDKAssist.Assets.Helpers.VSIPHelper.FindItemByName(
							this.Project.ProjectItems,
							Path.GetFileName(deploymentFile),
							false) != null)
					{
						VSSDKAssist.Assets.Helpers.TFSHelper.CheckOutFile(VisualStudio, deploymentFile);

						executeProcessAction.Execute();
					}
					else
					{
						executeProcessAction.Execute();

						using(AddItemFromFileToProjectAction addItemFromFileToProjectAction = new AddItemFromFileToProjectAction())
						{
							addItemFromFileToProjectAction.Site = this.Site;
							addItemFromFileToProjectAction.Project = this.Project;
							addItemFromFileToProjectAction.SourceFileName = deploymentFile;

							addItemFromFileToProjectAction.Execute();
						}
					}
				}
			}
		}

		private string GetArguments(string assemblyFile, string projectPath, ref string deploymentFile)
		{
			string arguments = string.Empty;
			string depFile;

			if(assemblyFile.Contains(" "))
			{
				assemblyFile = string.Concat("\"", assemblyFile, "\"");
			}

			switch(this.RegistrationMethod)
			{
				case RegistrationMethod.Assembly:
					arguments += "/assembly ";
					break;
				case RegistrationMethod.CodeBase:
					arguments += "/codebase ";
					break;
				case RegistrationMethod.Default:
					break;
				default:
					break;
			}

			switch(this.DeploymentInfo)
			{
				case DeploymentInfo.RegFile:
					deploymentFile =
						Path.Combine(projectPath,
							string.Concat(deploymentFile, Properties.Resources.RegExtension));

					depFile = deploymentFile;

					if(depFile.Contains(" "))
					{
						depFile = string.Concat("\"", depFile, "\"");
					}

					arguments +=
						string.Format(
							CultureInfo.CurrentCulture,
							"/regfile:{0} {1}",
							depFile,
							assemblyFile);
					break;
				case DeploymentInfo.WixFile:
					deploymentFile =
						Path.Combine(projectPath,
							string.Concat(deploymentFile, Properties.Resources.WixExtension));

					depFile = deploymentFile;

					if(depFile.Contains(" "))
					{
						depFile = string.Concat("\"", depFile, "\"");
					}

					arguments +=
						string.Format(
							CultureInfo.CurrentCulture,
							"/wixfile:{0} {1}",
							depFile,
							assemblyFile); ;
					break;
				default:
					deploymentFile =
						Path.Combine(projectPath,
							string.Concat(deploymentFile, Properties.Resources.RegExtension));

					depFile = deploymentFile;

					if(depFile.Contains(" "))
					{
						depFile = string.Concat("\"", depFile, "\"");
					}

					arguments +=
						string.Format(
							CultureInfo.CurrentCulture,
							"/regfile:{0} {1}",
							depFile,
							assemblyFile);
					break;
			}

			return arguments;
		}
		#endregion
	}
}